#include "tcp_ip_at.h"

extern char wifiATCmdString[WIFI_AT_CMD_MAX_LEN]; // AT指令字符串
char wifiReciveData[WIFI_DATA_LENGTH];            // 接收数据缓冲区

/*
*AT+CIPSTATUS—查询⽹网络连接信息
AT+CIPSTATUS
*返回：
STATUS:<stat>
+CIPSTATUS:<link ID>,<type>,<remote IP>,<remote port>,<local port>,<tetype>
*参数说明：
• <stat>：ESP8266 Station 接⼝口的状态
    ‣ 2：ESP8266 Station 已连接 AP，获得 IP 地址
    ‣ 3：ESP8266 Station 已建⽴立 TCP 或 UDP 传输
    ‣ 4：ESP8266 Station 断开⽹网络连接
    ‣ 5：ESP8266 Station 未连接 AP
• <link ID>：⽹网络连接 ID (0 ~ 4)，⽤用于多连接的情况
• <type>：字符串串参数，"TCP" 或者 "UDP"
• <remote IP>：字符串串，远端 IP 地址
• <remote port>：远端端⼝口值
• <local port>：ESP8266 本地端⼝口值
• <tetype>：
    ‣ 0：ESP8266 作为客户端
    ‣ 1：ESP8266 作为服务器器
*/

/*
*AT+CIPDOMAIN一域名解析功能
*AT+CIPDOMAIN=<domain name>
*返回：
+CIPDOMAIN:<IP address>
OK
或者
DNS Fail
ERROR
*参数说明：<domain name>：待解析的域名，可⽀支持⻓长度⼩小于 64 的域名
*示例：
AT+CWMODE=1 // set Station mode
AT+CWJAP="SSID","password" // access to the internet
AT+CIPDOMAIN="iot.espressif.cn" // DNS function
*/
void wifiAT_cipdomain(char *domain_name)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN); // 清空AT指令字符串
    memcpy(wifiATCmdString, WIFI_AT_CIPDOMAIN, sizeof(WIFI_AT_CIPDOMAIN));
    strcat(wifiATCmdString, domain_name);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSTART一建立 TCP 连接，UDP 传输或 SSL 连接
*建立TCP连接：
**TCP 单连接 (AT+CIPMUX=0) 时：AT+CIPSTART=<type>,<remote IP>,<remote port>[,<TCP keep alive>]
**TCP 多连接 (AT+CIPMUX=1) 时：AT+CIPSTART=<link ID>,<type>,<remote IP>,<remote port>[,<TCP keep alive>]
**响应：
OK
或
ERROR
如果连接已经存在，则返回
ALREADY CONNECTED
**参数说明：
    • <link ID>：⽹网络连接 ID (0 ~ 4)，⽤用于多连接的情况
    • <type>：字符串串参数，连接类型，"TCP"，"UDP"或"SSL"
    • <remote IP>：字符串串参数，远端 IP 地址
    • <remote port>：远端端⼝口号
    • [<TCP keep alive>]：TCP keep-alive 侦测时间，默认关闭此功能
        ‣ 0：关闭 TCP keep-alive 功能
        ‣ 1 ~ 7200：侦测时间，单位为 1s
**示例：
AT+CIPSTART="TCP","iot.espressif.cn",8000
AT+CIPSTART="TCP","192.168.101.110",1000
*
*建立UDP传输：
**单连接模式 (AT+CIPMUX=0) 时：AT+CIPSTART=<type>,<remote IP>,<remote port>[,(<UDP local port>),(<UDP mode>)]
**多连接模式 (AT+CIPMUX=1) 时：AT+CIPSTART=<link ID>,<type>,<remote IP>,<remote port>[,(<UDP local port>),(<UDP mode>)]
**响应：
OK
或
ERROR
如果连接已经存在，则返回：
ALREADY CONNECTED
**参数说明：
• <link ID>：⽹网络连接 ID (0 ~ 4)，⽤用于多连接的情况
• <type>：字符串串参数，连接类型，"TCP"，"UDP"或"SSL"
• <remote IP>：字符串串参数，远端 IP 地址
• <remote port>：远端端⼝口号
• [<UDP local port>]：UDP 传输时，设置本地端⼝口
• [<UDP mode>]：UDP 传输的属性，若透传，则必须为 0
‣ 0：收到数据后，不不更更改远端⽬目标，默认值为 0
‣ 1：收到数据后，改变⼀一次远端⽬目标
‣ 2：收到数据后，改变远端⽬目标
⚠ 注意：
使⽤用 <UDP mode> 必须先填写 <UDP local port>。
**示例：
AT+CIPSTART="UDP","192.168.101.110",1000,1002,2
*
*建立SSL连接：
• ESP8266 最多仅⽀支持建⽴立 1 个 SSL 连接。
• SSL 连接不不⽀支持透传。
• SSL 需要占⽤用较多空间，如果空间不不⾜足，会导致系统重启。⽤用户可以使⽤用指令AT+CIPSSLSIZE=<size> 增⼤SSL缓存。
**AT+CIPSTART=[<link ID>,]<type>,<remote IP>,<remote port>[,<TCP keep alive>]
**响应：
OK
或
ERROR
如果连接已经存在，则返回：
ALREADY CONNECTED
**参数说明：
• <link ID>：⽹网络连接 ID (0 ~ 4)，⽤用于多连接的情况
• <type>：字符串串参数，连接类型，"TCP"，"UDP"或"SSL"
• <remote IP>：字符串串参数，远端 IP 地址
• <remote port>：远端端⼝口号
• [<TCP keep alive>]：TCP keep-alive 侦测时间，默认关闭此功能
    ‣ 0：关闭 TCP keep-alive 功能
    ‣ 1 ~ 7200：侦测时间，单位为 1s
**示例：
AT+CIPSSLSIZE=4096
AT+CIPSTART="SSL","iot.espressif.cn",8443
*
*cmdType:0表示TCP连接，1表示UDP连接，2表示SSL连接
*cmdLinkNum:0表示单连接，1表示多连接
*/
void wifiAT_cipstart(uint8_t cmdType, uint8_t cmdLinkNum, char *linkId, char *linkType, char *remoteIP,
                     char *remotePort, char *tcpKeepAlive, char *udpLocalPort, char *udpMode)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN); // 清空AT指令字符串
    memcpy(wifiATCmdString, WIFI_AT_CIPSTART, sizeof(WIFI_AT_CIPSTART));
    switch (cmdLinkNum)
    {
    case 0: // TCP
    {
        if (cmdType)
        {
            // 多连接
            strcat(wifiATCmdString, linkId);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, linkType);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remoteIP);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remotePort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, tcpKeepAlive);
        }
        else
        {
            // 单连接
            strcat(wifiATCmdString, linkType);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remoteIP);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remotePort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, tcpKeepAlive);
        }
    }
    break;
    case 1: // UDP
    {
        if (cmdType)
        {
            // 多连接
            strcat(wifiATCmdString, linkId);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, linkType);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remoteIP);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remotePort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, udpLocalPort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, udpMode);
        }
        else
        {
            // 单连接
            strcat(wifiATCmdString, linkType);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remoteIP);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remotePort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, udpLocalPort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, udpMode);
        }
    }
    break;
    case 2: // SSL
    {
        if (cmdType)
        {
            // 多连接
            strcat(wifiATCmdString, linkId);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, linkType);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remoteIP);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remotePort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, tcpKeepAlive);
        }
        else
        {
            // 单连接
            strcat(wifiATCmdString, linkType);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remoteIP);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remotePort);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, tcpKeepAlive);
        }
    }
    break;
    default:
        break;
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
 *AT+CIPSSLSIZE—设置 SSL Buffer 容量量
 *AT+CIPSSLSIZE=<size>
 *返回值：OK
 *参数说明：<size>：SSL buffer ⼤大⼩小，取值范围：[2048, 4096]。
 *示例：AT+CIPSSLSIZE=4096
 */
void wifiAT_CIPSSLSIZE(char *size)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSSLSIZE, sizeof(WIFI_AT_CIPSSLSIZE));
    strcat(wifiATCmdString, size);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSSLCCONF_配置 SSL Client
• 如需设置本指令，请在建⽴SSL连接之前调⽤用。本设置对所有SSL连接均⽣生效。
• 如需证书认证，请参考⽂文档ESP8266 SSL指南第4章ESP8266作为SSL Client，⽣成SSL所需证书。
    - esp_cert_private_key.bin 默认烧录到地址 0xFC000
    - esp_ca_cert.bin 默认烧录到地址 0xFB000
    - ⽤用户可以⾃自⾏行行修改 user_main.c 中的SYSTEM_PARTITION_SSL_CLIENT_CERT_PRIVKEY_ADDR 和
    SYSTEM_PARTITION_SSL_CLIENT_CA_ADDR 地址，重新编译指定位置。
• 本设置将保存到 flash ⽤用户参数区。
*查询指令：
AT+CIPSSLCCONF?
*响应：
+CIPSSLCCONF:<SSL mode>
OK
*设置指令：
AT+CIPSSLCCONF=<SSL mode>
*返回值：OK
*参数说明：
• <SSL mode>：SSL 认证⽅方式
    ‣ bit0：是否加载 cert 和 private key，以供 server 认证
    ‣ bit1：是否加载 CA，认证 server 的 cert 和 private key
*示例：
AT+CWMODE=1 // 设置 sta 模式
AT+CWJAP="SSID","PASSWORD" // 连接路路由器器，连接⽹网络
AT+CIPSNTPCFG=1,8 // 设置时区
AT+CIPSNTPTIME? // 查询当前时间
AT+CIPSSLCCONF=2
AT+CIPSTART="SSL","192.168.3.38",8443
*
*
*cmdType: 0:查询 1:设置
*/
void wifiAT_CIPSSLCCONF(int cmdType, char *sslMode)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSSLCCONF, sizeof(WIFI_AT_CIPSSLCCONF));
    if (cmdType)
    {
        // 设置
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, sslMode);
    }
    else
    {
        // 查询
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSEND—发送数据
*设置指令：
    1. 单连接时：(+CIPMUX=0)
    AT+CIPSEND=<length>
    2. 多连接时：(+CIPMUX=1)
    AT+CIPSEND=<link ID>,<length>
    3. 如果是 UDP 传输，可以设置远端 IP 和端⼝：
    AT+CIPSEND=[<link ID>,]<length>[,<remote IP>,<remote port>]
    功能：在普通传输模式时，设置发送数据的⻓度。
*响应：
    发送指定⻓度的数据。收到此命令后先换⾏行行返回 >，然后开始接收串⼝数据，当数据⻓长度满 <length> 时发送数据，回到普通指令模式，等待下⼀条AT指令。
    如果未建⽴连接或连接被断开，返回：ERROR
    如果数据发送成功，返回：SEND OK
    如果数据发送失败，返回：SEND FAIL
*执行指令：
    AT+CIPSEND
    功能：在透传模式时，开始发送数据。
*响应：
    收到此命令后先换⾏行行返回 >。进⼊透传模式发送数据，每包最⼤2048字节，或者每包数据以 20 ms 间隔区分。
    当输⼊入单独⼀一包 +++ 时，返回普通AT指令模式。发送 +++ 退出透传时，请⾄至少间隔1秒再发下⼀一条 AT 指令。
    本指令必须在开启透传模式以及单连接下使⽤。
    若为 UDP 透传，指令 AT+CIPSTART 参数<UDP mode> 必须为 0。
*参数说明：
    • <link ID>：⽹网络连接 ID 号 (0 ~ 4)，⽤用于多连接的情况
    • <length>：数字参数，表明发送数据的⻓长度，最⼤长度为 2048
    • [<remote IP>]：UDP传输可以设置对端 IP
    • [<remote port>]：UDP传输可以设置对端⼝
*
*cmdType: 0:设置 1:执行
*linkNum: 0:单连接 1:多连接
*udpFlag: 0:不是UDP,1:是UDP
*/
void wifiAT_CIPSEND(int cmdType, int linkNum, int udpFlag, char *linkID, char *length, char *remoteIP, char *remotePort)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSEND, sizeof(WIFI_AT_CIPSEND));
    // 设置指令
    if (cmdType == 0)
    {
        if (linkNum == 0)
        {
            strcat(wifiATCmdString, "=");
            strcat(wifiATCmdString, length);
        }
        else
        {
            if (udpFlag)
            {
                // UDP传输
                strcat(wifiATCmdString, "=");
                strcat(wifiATCmdString, linkID);
                strcat(wifiATCmdString, ",");
                strcat(wifiATCmdString, length);
                strcat(wifiATCmdString, ",");
                strcat(wifiATCmdString, remoteIP);
                strcat(wifiATCmdString, ",");
                strcat(wifiATCmdString, remotePort);
            }
            else
            {
                strcat(wifiATCmdString, "=");
                strcat(wifiATCmdString, linkID);
                strcat(wifiATCmdString, ",");
                strcat(wifiATCmdString, length);
            }
        }
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSENDEX—发送数据
    1. 单连接时：(+CIPMUX=0)
    AT+CIPSENDEX=<length>
    2. 多连接时：(+CIPMUX=1)
    AT+CIPSENDEX=<link ID>,<length>
    3. 如果是 UDP 传输，可以设置远端 IP 和端⼝口：
    AT+CIPSENDEX=[<link ID>,]<length>[,<remote IP>,<remote port>]
    指令功能：在普通传输模式时，设置发送数据的⻓长度。
*响应：
    发送指定⻓长度的数据。
    收到此命令后先换⾏行行返回 >，然后开始接收串串⼝口数据，当数据⻓长度满 length 或者遇到字符'\0'时，发送数据。
    如果未建⽴立连接或连接被断开，返回：ERROR
    如果数据发送成功，返回：SEND OK
    如果数据发送失败，返回：SEND FAIL
*参数说明：
    •<link ID>：⽹网络连接 ID 号 (0 ~ 4)，⽤用于多连接的情况
    • <length>：数字参数，表明发送数据的⻓长度，最⼤大⻓长度为 2048
    • 当接收数据⻓长度满 length 或者遇到字符 \0 时，发送数据，回到普通指令模式，等待下⼀一
    条 AT 指令。
    • ⽤用户如需发送 \0，请转义为 \\0。
*linkNum: 0:单连接 1:多连接
*udpFlag: 0:不是UDP,1:是UDP
*/
void wifiAT_CIPSENDEX(int linkNum, int udpFlag, char *linkID, char *length, char *remoteIP, char *remotePort)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSENDEX, sizeof(WIFI_AT_CIPSENDEX));
    if (linkNum == 0)
    {
        // 单连接
        strcat(wifiATCmdString, length);
    }
    else
    {
        // 多连接
        if (udpFlag)
        {
            // UDP传输
            strcat(wifiATCmdString, linkID);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, length);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remoteIP);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, remotePort);
        }
        else
        {
            // 非UDP传输
            strcat(wifiATCmdString, linkID);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, length);
        }
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSENDBUF一数据写入 TCP 发包缓存
    1. 单连接时：(+CIPMUX=0)
    AT+CIPSENDBUF=<length>
    2. 多连接时：(+CIPMUX=1)
    AT+CIPSENDBUF=<link ID>,<length>
*响应：
<本次 segment ID>,<已成功发送的 segment ID>
OK
>
• 收到此命令后先返回 packet ID，再换⾏行行返回 >，然后开始接收串串⼝口数据，当数据⻓长度满
length 或者遇到字符 \0 时，发送数据；超过 length 的数据丢弃，并提示 busy。
• 如果未建⽴立连接或并⾮非 TCP 连接或 buffer 满等出错，返回：ERROR
• 如果某包数据发送成功
    ‣ 单连接时，返回：<segment ID>,SEND OK
    ‣ 多连接时，返回：<link ID>,<segment ID>,SEND OK
• 如果数据发送失败，返回：SEND FAIL
*参数说明：
    • <link ID>：⽹网络连接 ID 号 (0 ~ 4)，⽤用于多连接的情况；
    • <segment ID>：uint32，给每包写⼊入数据分配的 ID，从 1 开始计数，每写⼊⼀包则⾃加⼀，计数满则重新从 1 计数；
    • <length>：数据⻓长度，超过⻓长度的数据则丢弃。
本指令将数据写⼊TCP发包缓存，⽆需等待 SEND OK，可连续调⽤；发送成功后，会返回数据包 ID 及 SEND OK。
在数据没有传⼊完成时，传⼊+++可退出发送，之前传⼊的数据将直接丢弃。SSL连接不支持使⽤本指令。
*
*
*linkNum: 0:单连接 1:多连接
*/
void wifiAT_CIPSENDBUF(int linkNum, char *linkID, char *length)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSENDBUF, sizeof(WIFI_AT_CIPSENDBUF));
    if (linkNum == 0)
    {
        // 单连接
        strcat(wifiATCmdString, length);
    }
    else
    {
        // 多连接
        strcat(wifiATCmdString, linkID);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, length);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPBUFRESET一重新计数
    1. 单连接时：(+CIPMUX=0)
    AT+CIPBUFRESET
    2. 多连接时：(+CIPMUX=1)
    AT+CIPBUFRESET=<link ID>
*响应：
OK
如果有数据包未发送完毕，或者连接不不存在，则返回：ERROR
*参数说明：
<link ID>：⽹网络连接 ID 号 (0 ~ 4)，⽤用于多连接的情况。
*
*linkNum: 0:单连接 1:多连接
*/
void wifiAT_CIPBUFRESET(int linkNum, char *linkID)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPBUFRESET, sizeof(WIFI_AT_CIPBUFRESET));
    if (linkNum)
    {
        // 多连接
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, linkID);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPBUFSTATUS—查询 TCP 发包缓存的状态
    1. 单连接时：(+CIPMUX=0)
    AT+CIPBUFSTATUS
    2. 多连接时：(+CIPMUX=1)
    AT+CIPBUFSTATUS=<link ID>
*响应：
<下次的 segment ID>,<已发送的 segment ID>,<成功发送的segment ID>,<remain buffer size>,<queue number>
OK
*参数说明：
    • <下次的 segment ID>: 下次调⽤用 AT+CIPSENDBUF 将分配的 ID；
    • <已发送的 segment ID>：已发送的 TCP 数据包 ID；
    • 仅当 <下次的 segment ID> - <已发送的 segment ID> = 1 的情况下，可调⽤AT+CIPBUFRESET 重置计数。
    • <成功发送的segment ID>：成功发送的 TCP 数据包 ID；
    • <remain buffer size>：TCP 发包缓存剩余的空间；
    • <queue number>: 底层可⽤用的 queue 数⽬目，并不不可靠，仅供参考。
*示例：
例例如，单连接时 AT+CIPBUFSTATUS 的返回值为：
20,15,10,200,7
说明：
    • 20：表示当前数据包序号已经分配到了了 19，下次调⽤AT+CIPSENDBUF将为数据包分配序号20；
    • 15：表示当前已发送了序号为15的数据包，但并不不⼀一定发送成功了；
    • 10：表示成功发送到了序号为 10 的数据包；
    • 200：表示⽹络层TCP发包缓存剩余的空间为200bytes；
    • 7：表示当前⽹络层还剩余7个queue供数据传输，仅供参考，并不可靠；当queue为0时，不允许数据发送。
*
*
*linkNum: 0:单连接 1:多连接
*/
void wifiAT_CIPBUFSTATUS(int linkNum, char *linkID)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPBUFSTATUS, sizeof(WIFI_AT_CIPBUFSTATUS));
    if (linkNum)
    {
        // 多连接
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, linkID);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPCHECKSEQ一查询写入TCP发包缓存的某包是否发送成功
    1. 单连接时：(+CIPMUX=0)
    AT+CIPCHECKSEQ=<segment ID>
    2. 多连接时：(+CIPMUX=1)
    AT+CIPCHECKSEQ=<link ID>,<segment ID>
*响应：
<link ID>,]<segment ID>,<status>
OK
*参数说明：
    • 最多记录最后的 32 个 segment ID 数据包的状态。
    • [<link ID>]：⽹网络连接 ID (0~4)，⽤用于多连接的情况；
    • <segment ID>：调⽤用 AT+CIPSENDBUF 写⼊入数据时分配的 ID;
    • <status>：
        ‣ FALSE：发送失败；
        ‣ TRUE：发送成功。
*注意：
本指令基于AT+CIPSENDBUF实现功能。
*
*linkNum: 0:单连接 1:多连接
*/
void wifiAT_CIPCHECKSEQ(int linkNum, char *linkID, char *segmentID)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPCHECKSEQ, sizeof(WIFI_AT_CIPCHECKSEQ));
    if (linkNum)
    {
        // 多连接
        strcat(wifiATCmdString, linkID);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, segmentID);
    }
    else
    {
        strcat(wifiATCmdString, segmentID);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPCLOSEMODE-设置 TCP 连接的断开方式
    1. 单连接时：(+CIPMUX=0)
    AT+CIPCLOSEMODE=<enable_abort>
    2. 多连接时：(+CIPMUX=1)
    AT+CIPCLOSEMODE=<link ID>,<enable_abort>
*响应：
OK
*参数说明：
<link ID>：连接 ID 号
<enable_abort>：断开⽅方式；0，正常断开；1，abort 强制断开。
*注意：
    • 默认 TCP 连接为正常断开模式。⼀一般不不建议使⽤用 abort 强制断开模式。
    • 如需设置为 abort 强制断开模式：
        - 需在 TCP 连接建⽴立之后设置；
        - 设置仅对当次连接有效；如果当前 TCP 连接断开，重新建⽴立连接后，需要重新设置；
    • 设置仅对普通 TCP 连接有效，对 SSL 连接⽆无效。
*示例：
AT+CIPSTART=0,"TCP","192.168.3.60",3400
AT+CIPCLOSEMODE=0,1
AT+CIPCLOSE=0
*
*linkNum: 0:单连接 1:多连接
*/
void wifiAT_CIPCLOSEMODE(int linkNum, char *linkID, char *enableAbort)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPCLOSEMODE, sizeof(WIFI_AT_CIPCLOSEMODE));
    if (linkNum)
    {
        // 多连接
        strcat(wifiATCmdString, linkID);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, enableAbort);
    }
    else
    {
        strcat(wifiATCmdString, enableAbort);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPCLOSE-关闭 TCP/UDP 连接
*设置指令（⽤用于多连接的情况）：
AT+CIPCLOSE=<link ID>
功能：关闭 TCP/UDP 传输。
执⾏指令（⽤用于单连接的情况）：
AT+CIPCLOSE
*响应：
OK
*参数说明：
<link ID>：需要关闭的连接ID号。当ID为5时，关闭所有连接。(开启server后ID为5无效）
*
*linkNum: 0:单连接 1:多连接
*/
void wifiAT_CIPCLOSE(int linkNum, char *linkID)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPCLOSE, sizeof(WIFI_AT_CIPCLOSE));
    if (linkNum)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, linkID);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIFSR—查询本地 IP 地址
AT+CIFSR
*响应：
+CIFSR:APIP,<SoftAP IP address>
+CIFSR:APMAC,<SoftAP MAC address>
+CIFSR:STAIP,<Station IP address>
+CIFSR:STAMAC,<Station MAC address>
OK
*参数说明：
<IP address>：
ESP8266 SoftAP 的 IP 地址
ESP8266 Station 的 IP 地址
<MAC address>：
ESP8266 SoftAP 的 MAC 地址
ESP8266 Station 的 MAC 地址
*注意：
ESP8266 Station IP 需连上 AP 后，才可以查询。
*/

/*
*AT+CIPMUX-设置多连接
*查询指令：AT+CIPMUX?
 响应：
+CIPMUX:<mode>
OK
*设置指令：AT+CIPMUX=<mode>
*参数说明：
    <mode>：
        ‣ 0：单连接模式
        ‣ 1：多连接模式
*注意：
    默认为单连接；
        • 只有⾮非透传模式 (AT+CIPMODE=0)，才能设置为多连接；
        • 必须在没有连接建⽴立的情况下，设置连接模式；
        • 如果建⽴立了了 TCP 服务器器，想切换为单连接，必须关闭服务器器 (AT+CIPSERVER=0)，服务器器仅⽀持多连接。
*示例：AT+CIPMUX=1
*
*cmdType: 0:查询 1:设置
*/
void wifiAT_CIPMUX(int cmdType, char *mode)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPMUX, sizeof(WIFI_AT_CIPMUX));
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, mode);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSERVER-建立TCP服务器
*设置指令：AT+CIPSERVER=<mode>[,<port>]
*响应：OK
*参数说明：
    • <mode>：
        ‣ 0：关闭服务器器
        ‣ 1：建⽴立服务器器
    • <port>：端⼝口号，默认为 333。
*注意：
    • 多连接情况下 (AT+CIPMUX=1)，才能开启 TCP 服务器器。
    • 创建 TCP 服务器器后，⾃自动建⽴立 TCP 服务器器监听。
    • 当有 TCP 客户端接⼊入，会⾃自动占⽤用⼀一个连接 ID。
*示例：
AT+CIPMUX=1
AT+CIPSERVER=1,1001
*/
void wifiAT_CIPSERVER(char *mode, char *port)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSERVER, sizeof(WIFI_AT_CIPSERVER));
    strcat(wifiATCmdString, "=");
    strcat(wifiATCmdString, mode);
    strcat(wifiATCmdString, ",");
    strcat(wifiATCmdString, port);
}

/*
*AT+CIPSERVERMAXCONN一设置服务器允许建立的最大连接数
*设置指令：AT+CIPSERVERMAXCONN=<num>
*响应：OK
*参数说明：
<num>：服务器器允许建⽴立的最⼤大连接数，取值范围：[1, 5]。
*查询指令：AT+CIPSERVERMAXCONN?
*响应：
+CIPSERVERMAXCONN:<num>
OK
*注意：
如需设置最⼤大连接数，请在创建服务器器之前设置。
*示例：
AT+CIPMUX=1
AT+CIPSERVERMAXCONN=2
AT+CIPSERVER=1,80
*
*
*cmdType: 0:查询 1:设置
*/
void wifiAT_CIPSERVERMAXCONN(int cmdType, char *num)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSERVERMAXCONN, sizeof(WIFI_AT_CIPSERVERMAXCONN));
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, num);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPMODE-设置传输模式
*设置指令：AT+CIPMODE=<mode>
*响应：OK
*查询指令：AT+CIPMODE?
*响应：
+CIPMODE:<mode>
OK
*参数说明：
<mode>：
    ‣ 0：普通传输模式
    ‣ 1：透传模式，仅⽀支持 TCP 单连接和 UDP 固定通信对端的情况
*注意：
    • 本设置不不保存到 Flash。
    • 透传模式传输时，如果连接断开，ESP8266 会不不停尝试重连，此时单独输⼊+++退出透传，则停止重连；普通传输模式则不会重连，提示连接断开。
*示例：
AT+CIPMODE=1
*/
void wifiAT_CIPMODE(int cmdType, char *mode)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPMODE, sizeof(WIFI_AT_CIPMODE));
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, mode);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+SAVETRANSLINK—保存透传到 Flash
*保存透传（TCP 单连接）到 Flash
**AT+SAVETRANSLINK=<mode>,<remote IP or domain name>,<remote port>[,<type>,<TCP keep alive>]
**响应：OK
**参数说明：
    • <mode>：
        ‣ 0：取消开机透传
        ‣ 1：保存开机进⼊入透传模式
    • <remote IP>：远端 IP 或者域名
    • <remote port>：远端端⼝口
    • [<type>]（选填参数）：TCP 或者 UDP，缺省默认为 TCP
    • [<TCP keep alive>]（选填参数）：TCP keep-alive 侦测，缺省默认关闭此功能
        ‣ 0：关闭 TCP keep-alive 功能
        ‣ 1 ~ 7200：侦测时间，单位为秒
**注意：
    •本设置将透传模式及建⽴的TCP连接均保存在Flash system parameter区域，下次上电⾃动
    建⽴TCP连接并进入透传。
    •只要远端 IP，端⼝的值符合规范，本设置就会被保存到 Flash。
**示例：
AT+SAVETRANSLINK=1,"192.168.6.110",1002,"TCP"
*保存透传（UDP 传输）到 Flash
**AT+SAVETRANSLINK=<mode>,<remote IP>,<remote port>,<type>[,<UDP local port>]
**响应：OK
**参数说明：
    • <mode>：
        ‣ 0：取消开机透传
        ‣ 1：保存开机进⼊入透传模式
    • <remote IP>：远端 IP
    • <remote port>：远端端⼝口
    • <type>：UDP，缺省默认为 TCP
    • [<UDP local port>]（选填参数）：开机进⼊入 UDP 传输时，使⽤用的本地端⼝
**注意：
    • 本设置将透传模式及建⽴的UDP传输均保存在Flash⽤户参数区，下次上电⾃动建⽴UDP
    传输并进⼊入透传。
    • 只要远端IP，端⼝的数值符合规范，本设置就会被保存到Flash。
**示例：
AT+SAVETRANSLINK=1,"192.168.6.110",1002,"UDP",1005
*
*cmdType: 0-TCP, 1-UDP
*/
void wifiAT_SAVETRANSLINK(int cmdType, char *mode, char *remoteIP, char *remotePort, char *type, char *localPort, char *keepAliveTime)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_SAVETRANSLINK, sizeof(WIFI_AT_SAVETRANSLINK));
    if (cmdType)
    {
        strcat(wifiATCmdString, mode);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, remoteIP);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, remotePort);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, type);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, localPort);
    }
    else
    {
        strcat(wifiATCmdString, mode);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, remoteIP);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, remotePort);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, type);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, keepAliveTime);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSTO—设置TCP服务器超时时间
*查询指令：AT+CIPSTO?
*响应：
+CIPSTO:<time>
OK
*设置指令：AT+CIPSTO=<time>
*响应：OK
*参数说明：
<time>：TCP 服务器器超时时间，取值范围 0 ~ 7200s。
*注意：
    • ESP8266作为TCP服务器，会断开⼀直不通信直⾄超时了的TCP客户端连接。
    • 如果设置AT+CIPSTO=0，则永远不会超时，不建议这样设置。
*示例：
AT+CIPMUX=1
AT+CIPSERVER=1,1001
AT+CIPSTO=10
*
*cmdType: 0-查询， 1-设置
*/
void wifiAT_CIPSTO(int cmdType, char *time)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSTO, sizeof(WIFI_AT_CIPSTO));
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, time);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+PING-Ping功能
*AT+PING=<IP>
功能：ping 功能。
*响应：
+<time>
OK
或
+timeout
ERROR
*参数说明：
    • <IP>：字符串串参数，IP 地址
    • <time>：ping 响应时间
*示例：
AT+PING="192.168.1.1"
AT+PING="www.baidu.com"
*/
void wifiAT_PING(char *ip)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_PING, sizeof(WIFI_AT_PING));
    strcat(wifiATCmdString, "=");
    strcat(wifiATCmdString, ip);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIUPDATE一通过Wi-Fi升级软件
*AT+ CIUPDATE
*响应：
+CIPUPDATE:<n>
OK
*参数说明：
    <n>：
        • 1：找到服务器器
        • 2：连接到服务器器
        • 3：获得软件版本
        • 4：开始升级
*注意：
•若直接使⽤用乐鑫提供的 AT BIN (/ESP8266_NONOS_SDK/bin/at)，本指令将从 Espressif
Cloud 下载 AT 固件升级。
•若⽤用户⾃自行编译AT源代码，则请⾃自⾏实现AT+CIUPDATE指令的升级功能，乐鑫提供本地升级
的Demo作为参考（/ESP8266_NONOS_SDK/example/at）。
•建议升级AT固件后，调⽤AT+RESTORE恢复出⼚设置，重新初始化。
*/

/*
*AT+CIPDINFO一接收网络数据时是否提示对端IP 和端口
*AT+CIPDINFO=<mode>
功能：接收⽹网络数据时，+IPD 是否提示对端 IP 和端⼝
*响应：OK
*参数说明：
<mode>：字符串参数，IP 地址
    • 0：不不显示对端 IP 和端⼝
    • 1：显示对端 IP 和端⼝
*示例：
AT+CIPDINFO=1
*/
void wifiAT_CIPDINFO(char *mode)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPDINFO, sizeof(WIFI_AT_CIPDINFO));
    strcat(wifiATCmdString, mode);
    strcat(wifiATCmdString, "\r\n");
}

/*
*+IPD一接收网络数据
*单连接时：(+CIPMUX=0)+IPD,<len>[,<remoteIP>,<remote port>]:<data>
*多连接时：(+CIPMUX=1)+IPD,<link ID>,<len>[,<remote IP>,<remote port>]:<data>
*参数说明：
    此指令在普通指令模式下有效，ESP8266 接收到⽹络数据时向串串⼝发送+IPD和数据。
    • [<remote IP>]：⽹络通信对端IP，由指令AT+CIPDINFO=1使能显示
    • [<remote port>]：⽹络通信对端端⼝，由指令AT+CIPDINFO=1使能
    • <link ID>：收到⽹网络连接的ID号
    • <len>：数据⻓长度
    • <data>：收到的数据
*
*linkNum: 0-单连接， 1-多连接
*/
void wifiAT_IPD(int linkNum, char *len, char *remoteIP, char *remotePort, char *data)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (linkNum)
        memcpy(wifiATCmdString, "(+CIPMUX=1)", sizeof("(+CIPMUX=1)"));
    else
        memcpy(wifiATCmdString, "(+CIPMUX=0)", sizeof("(+CIPMUX=0)"));
    strcat(wifiATCmdString, "+IPD,");
    strcat(wifiATCmdString, len);
    if (remoteIP != NULL && remotePort != NULL)
    {
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, remoteIP);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, remotePort);
    }
    strcat(wifiATCmdString, ":");
    strcat(wifiATCmdString, data);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPRECVMODE—设置TCP连接的数据接收⽅式
*设置指令：
AT+CIPRECVMODE=<mode>
*响应：
+CIPRECVMODE:<mode>
OK
*查询指令：
AT+CIPRECVMODE?
*响应：
OK
*参数说明：
<mode>：TCP 连接的数据接收⽅方式，默认为主动模式
    • 0：主动模式；收到 TCP 数据时，ESP8266 通过 +IPD 主动将数据通过串串⼝口发给 MCU；
    • 1：被动模式；ESP8266 默认使⽤用 2920 bytes的buffer⽤于缓存接收到的 TCP 数据，被动等待 MCU 读取；接收 buffer满后，将阻塞对端TCP发送数据。
*注意：
    • 本设置仅针对 TCP 连接的普通传输模式有效，对 UDP、SSL 连接和透传模式⽆无效。
    • 被动模式开启后，收到 TCP 数据时:
        - 多连接（AT+CIPMUX=1）将提示：+IPD,<link ID>,<len>
        - 单连接（AT+CIPMUX=0）将提示：+IPD,<len>
        - 其中 <len> 表示 buffer 中缓存的总数据⻓长度
*示例：AT+CIPRECVMODE=1
*
*cmdType: 1-设置指令， 0-查询指令
*/
void wifiAT_CIPRECVMODE(int cmdType, char *mode)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPRECVMODE, sizeof(WIFI_AT_CIPRECVMODE));
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, mode);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPRECVDATA一被动接收模式时，读取缓存的 TCP 数据
• 对于单连接模式（AT+CIPMUX=0）：
AT+CIPRECVDATA=<len>
• 对于多连接模式（AT+CIPMUX=1）：
AT+CIPRECVDATA=<link_id>,<len>
*响应：
+CIPRECVDATA,<actual_len>:<data>
OK
*参数说明：
<link_id>：多连接的连接 ID 号
<len>：读取的数据⻓长度，每次最多可读取 2048 字节
<actual_len>：实际读到的数据⻓长度
<data>：读到的 TCP 数据
*注意：
• 如果在缓存了TCP数据的情况下，当前连接断开，缓存的数据仍然保留，允许 MCU 读取，
直⾄至创建新的连接；如果新的同 ID 连接创建，则前⼀次连接缓存的数据将被丢弃。
*示例：
AT+CIPRECVMODE=1
//例如，收到提示 +IPD,0,100 第 0 号连接接收到 100 字节数据
AT+CIPRECVDATA=0,100 // 从 0 号连接读取 100 字节数据
*
*
*linkNum: 0-单连接， 1-多连接
*/
// 函数声明：wifiAT_CIPRECVDATA
// 参数：linkNum - 链接编号，link_id - 链接ID字符串，len - 数据长度字符串
void wifiAT_CIPRECVDATA(int linkNum, char *link_id, char *len)
{
    // 将wifiATCmdString数组清零，长度为WIFI_AT_CMD_MAX_LEN
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    // 将WIFI_AT_CIPRECVDATA的内容复制到wifiATCmdString中，长度为sizeof(WIFI_AT_CIPRECVDATA)
    memcpy(wifiATCmdString, WIFI_AT_CIPRECVDATA, sizeof(WIFI_AT_CIPRECVDATA));
    // 如果linkNum不为0，表示有多个链接
    if (linkNum)
    {
        // 将link_id字符串追加到wifiATCmdString中
        strcat(wifiATCmdString, link_id);
        // 在wifiATCmdString中追加一个逗号
        strcat(wifiATCmdString, ",");
        // 将len字符串追加到wifiATCmdString中
        strcat(wifiATCmdString, len);
    }
    // 如果linkNum为0，表示只有一个链接
    else
    {
        // 将len字符串追加到wifiATCmdString中
        strcat(wifiATCmdString, len);
    }
    // 在wifiATCmdString中追加回车换行符，表示命令结束
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPRECVLEN—被动接收模式时，查询缓存 TCP 数据的⻓长度
*AT+CIPRECVLEN?
*响应：
+CIPRECVLEN:<data length of link0>,<data length of link1>,<data length of link2>,<data length of link3>,<data length of link4>
OK
*参数说明：<data length of link>：被动接收模式时，该连接缓存的TCP数据长度
*示例：
AT+CIPRECVLEN?
+CIPRECVLEN:100,,,,,
OK
*/

/*
*AT+CIPSNTPCFG一设置时域和SNTP服务器
*查询指令：
AT+CIPSNTPCFG?
*响应：
+CIPSNTPCFG:<enable>,<timezone>,<SNTP server0>[,<SNTP server1>,<SNTP server2>]
OK
*设置指令：
AT+CIPSNTPCFG=<enable>[,<timezone>][,<SNTP server0>,<SNTP server1>,<SNTP server2>]
*响应：OK
*参数说明：
    • <enable>：
        ‣ 0：SNTP 未使能；
        ‣ 1：SNTP 使能。
    • <timezone>：时域，范围：[-11,13]；若 SNTP 使能，此参数必填；否则，⽆需填写；
    • <SNTP server0>：第⼀一个 SNTP 服务器器，可不填；
    • <SNTP server1>：第⼆二个 SNTP 服务器器，可不填；
    • <SNTP server2>：第三个 SNTP 服务器器，可不填。
*说明：
设置指令若未填写 SNTP server，则默认使⽤用
"cn.ntp.org.cn","ntp.sjtu.edu.cn","us.pool.ntp.org"
*示例：
AT+CIPSNTPCFG=1,8,"cn.ntp.org.cn","ntp.sjtu.edu.cn","us.pool.ntp.org"
*
*cmdType: 1-设置指令， 0-查询指令
*/
void wifiAT_CIPSNTPCFG(int cmdType, char *enable, char *timezone, char *server0, char *server1, char *server2)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CIPSNTPCFG, sizeof(WIFI_AT_CIPSNTPCFG));
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, enable);
        if (timezone != NULL)
        {
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, timezone);
        }
        if (server0 != NULL)
        {
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, server0);
        }
        if (server1 != NULL)
        {
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, server1);
        }
        if (server2 != NULL)
        {
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, server2);
        }
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSNTPTIME一查询SNTP时间
*查询指令：AT+CIPSNTPTIME?
*响应：
+CIPSNTPTIME:<time>
OK
*参数说明：
<time>：通过 SNTP 查询到的时间。
例例如，查询返回时间格式如下：
+CIPSNTPTIME:Thu Aug 04 14:48:05 2016
*示例：
AT+CWMODE=1 //设置为 station 模式
AT+CWJAP="DemoAP","password" //连接到路由器，连接网络
AT+CIPSNTPCFG=1,8 //设置时区
AT+CIPSNTPTIME? //查询时间
*/

/*
*AT+CIPDNS_CUR一自定义DNS服务器，不保存到Flash
*查询指令：AT+CIPDNS CUR?
*响应：
[+CIPDNS_CUR:<DNS server0>]
[+CIPDNS_CUR:<DNS server1>]
OK
*设置指令：AT+CIPDNS_CUR=<enable>[,<DNS server0>,<DNS server1>]
*响应：OK
*参数说明：
    • <enable>：
        ‣ 0：不不使能⾃自定义 DNS 服务器器；
        ‣ 1：使能⾃自定义 DNS 服务器器。
    • <DNS server0>：第⼀个 DNS 服务器器，可不填；
    • <DNS server1>：第⼆个 DNS 服务器器，可不填。
*说明：
    • 对于指令 AT+CIPDNS_CUR=1(即设置使能⾃自定义 DNS 服务器器，但未填写 <DNS server> 参数),
    则默认使⽤用 "208.67.222.222" 作为 DNS 服务器器。
    • 对于指令 AT+CIPDNS_CUR=0 （即不不使能⾃自定义 DNS 服务器)，则默认使⽤"208.67.222.222" 作为DNS服务器.
    并且，在与路路由器器交互的过程中，DNS 服务器器可能随着路由器的配置更改。
    • <DNS server0> 和 <DNS server1> 不不能设置为同⼀服务器器。
*示例：
AT+CIPDNS_CUR=1,"208.67.220.220"
*
*
*AT+CIPDNS_DEF一自定义DNS服务器，保存到Flash
*查询指令：AT+CIPDNS_DEF?
*设置指令：AT+CIPDNS_DEF=<enable>[,<DNS server0>,<DNS server1>]
*示例：AT+CIPDNS_DEF=1,"208.67.220.220"
*
*
*cmdType:0-查询指令，1-设置指令
*saveType:0-不保存到Flash，1-保存到Flash
*/
void wifiAT_CIPDNS(int cmdType, int saveType, char *enable, char *server0, char *server1)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPDNS_DEF, sizeof(WIFI_AT_CIPDNS_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPDNS_CUR, sizeof(WIFI_AT_CIPDNS_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, enable);
        if (server0 != NULL)
        {
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, server0);
        }
        if (server1 != NULL)
        {
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, server1);
        }
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}
